import helper._
import java.io.{File, RandomAccessFile}

// Config section; all these need to be defined
val topDir = "project/"
val tmpDir = "/tmp/svnRegress/"
val tmpDiffFile = tmpDir + "preCommitDiff"
val regTestDir = tmpDir + topDir + "qa/"
val regTestCmd = "local_regression"
val logFile = tmpDir + "log.txt"
val patchLevel = 2
val lockFileName = "regress_lock"
// end of config section

val workDir = tmpDir + topDir

def errMsg(s:String) = Console.err.println(s)
def exit(s:String) = { lock.release; lockChannel.close; errMsg(s); System.exit(1) }
def fullClean = {
    cwd(workDir)
    exec("svn revert -R ./")

    val svnStatus = execp("svn status")
    if (svnStatus._1 != 0) {
        exit("Couldn't retrieve status")
    }

    svnStatus._2 foreach {l =>
        val status = l.take(2).toString
        val rest = l.drop(2).trim

        status match {
            case "? " => if (exec("rm -r " + rest) != 0) exit("couldn't remove: " + rest)
            case "M " => exit("modified file found : " + rest)
            case "! " => 
            case _ => exit("unknown status " + l)
        }
    }
}


// check if workDir exists
if(!exists(workDir)) {
    errMsg("working dir not found. Please create it at: " + workDir)
    System.exit(1)
}

// Make sure we take the lock
val lockFile = new File(tmpDir + lockFileName)
lockFile.createNewFile
val lockChannel = new RandomAccessFile(lockFile, "rw").getChannel
val lock = lockChannel.lock


// check if tmpDiffFile doesn't exist
if(exists(tmpDiffFile)) {
    exit("Temporary Diff File already exists. Please remove it: " + tmpDiffFile)
}

cwd(workDir)

// Cleanup working dir
fullClean

// now update the working copy to latest revision
val svnUpdate = exec("svn up")
if (svnUpdate != 0) {
    exit("Couldn't update to latest revision")
}

// get the current changes
val repoPath = args(0)
val tid = args(1)
val svnChangedRaw = execp("svnlook changed -t " + tid + " " + repoPath)
if (svnChangedRaw._1 != 0) {
    exit("Couldn't get list of changes")
}

val svnChanged = svnChangedRaw._2.map(s => (s.take(2), s.drop(2)))
System.err.println("List of changes:")
svnChanged foreach {System.err.println(_)}

// get the diff
val svnDiff = execp("svnlook diff -t " + tid + " " + repoPath, tmpDiffFile)
if (svnDiff != 0) {
    exit("Couldn't get differences")
}
if (!exists(tmpDiffFile)) {
    exit("Couldn't find the diff file")
}

// apply the patch
val patchApply = exec("patch -p " + patchLevel + " -i " + tmpDiffFile)

// remove the diff file
exec ("rm -f " + tmpDiffFile)

if (patchApply != 0) {
    exit("Error applying patch!")
}

// Now run the regression test!
cwd(regTestDir)
val regRun = execp(regTestCmd, logFile)

if (regRun != 0) {
    val archiveName = tmpDir + "regrArchive" + tid + ".tar.gzip"
    val archive = exec("tar czf " + archiveName + " " + workDir)
    if (archive == 0) {
        errMsg("working directory archived at " + archiveName)
    } else {
        errMsg("Couldn't make archive!")
    }
}
// Cleanup the checked out directory
fullClean

if (regRun != 0) {
    exit("Regression run failed")
}

lock.release
lockChannel.close
